package cn.itcast.goods.user.web.servlet;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import cn.itcast.commons.CommonUtils;
import cn.itcast.goods.user.dao.UserDao;
import cn.itcast.goods.user.domain.User;
import cn.itcast.goods.user.service.UserService;
import cn.itcast.goods.user.service.exception.UserException;
import cn.itcast.servlet.BaseServlet;

/**
 * 用户模块的控制（WEB）层
 * @author GiantTao
 *
 */
public class UserServlet extends BaseServlet {
	private UserService userService = new UserService();
	
	public String updatePassword(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/**
		 * 1.封装表单数据
		 * 2.从session中获取uid
		 * 3.使用uid和表单中的oldPass和newPass来调用service方法
		 * 	*如果出现异常，保存异常信息到request中，转发到pwd.jsp
		 * 4.保存成功信息到request
		 * 5.转发到msg.jsp
		 */
		User userForm=CommonUtils.toBean(req.getParameterMap(), User.class);
		User user=(User)req.getSession().getAttribute("userSession");
		if(user==null){
			req.setAttribute("msg", "您还没有登录！");
			return "f:/jsps/user/login.jsp";
		}
		try {
			userService.updatePassword(user.getUid(),userForm.getLoginpass(),userForm.getNewpass());
			req.setAttribute("msg","修改密码成功！");
			req.setAttribute("code", "success");
			return "f:/jsps/msg.jsp";
		} catch (UserException e) {
			req.setAttribute("msg",e.getMessage());//保存异常信息到request
			req.setAttribute("user",userForm);//用户表单信息回显
			return "f:/jsps/user/pwd.jsp"; 
		}
	}
	
	/**
	 * 用户退出
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public String quit(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		req.getSession().invalidate();
		return "r:/jsps/user/login.jsp";
	}
	public String login(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/**
		 * 1.封装表单数据到User
		 * 2.校验表单数据
		 * 3.使用service查询，得到user
		 * 4.查看用户是否存在，若不存在：
		 * 	*保存错误信息：用户名或密码错误
		 * 	*保存用户数据，为了回显
		 * 	*转发到login.jsp
		 * 5.如果用户存在，查看状态，如果状态为false：
		 * 	*保存错误信息：您没有激活
		 * 	*保存表单数据：为了回显
		 * 	*转发到login.jsp
		 * 6.登录成功：
		 * 	*保存当前查询出的user到session中
		 * 	*保存当前用户名到cookie中，注意中文需要进行乱码处理
		 */
		User userForm=CommonUtils.toBean(req.getParameterMap(), User.class);
		Map<String, String> errors=validateLogin(userForm, req.getSession());
		/**
		 * 此处进行登录验证，由于使用了JS进行了验证，此处没有必要再次进行验证
		 */
		if(errors.size()>0){
//			req.setAttribute("errors", errors);
//			//若出现错误，需要将之前用户填写的信息进行回填
//			req.setAttribute("user", userForm);
//			return "f:/jsps/user/login.jsp";
		}
		/**
		 * 3.调用userService#login()方法
		 */
		User user= userService.login(userForm);
		if(user==null){
			req.setAttribute("msg", "用户名或密码错误！");
			req.setAttribute("user", userForm);
			return "f:/jsps/user/login.jsp";
		}else{
			if(user.getStatus()==0){
				req.setAttribute("msg", "请进行邮箱验证！");
				req.setAttribute("user", userForm);
				return "f:/jsps/user/login.jsp";
			}else{
				//保存当前用户信息到session中
				req.getSession().setAttribute("userSession",user);
				//保存当前用户名到cookies中，注意进行中文编码
				String loginname=user.getLoginname();
				loginname=URLEncoder.encode(loginname,"utf-8");
				Cookie cookie=new Cookie("loginname", loginname);
				cookie.setMaxAge(60*60*24*10);//保存10天
				resp.addCookie(cookie);
				return "r:/index.jsp";
			}
		}
	}
	
	
	/**
	 * 登陆校验
	 * @param user
	 * @param session
	 * @return
	 */
	Map<String, String> validateLogin(User user,HttpSession session){
		Map<String, String> errors=new HashMap<String, String>();
//		/**
//		 * 1.验证用户名
//		 */
//		String loginname=user.getLoginname();
//		if(loginname==null||loginname.trim().isEmpty()){
//			errors.put("loginname", "用户名不能为空！");
//		}else if(loginname.length()<3||loginname.length()>20){
//			errors.put("loginname", "用户名的长度必须在3-20字符之间！");
//		}else if(userService.ajaxValidateLoginname(loginname)) {
//			errors.put("loginname", "用户名不存在！");
//		}
//		/**
//		 * 2.验证登录密码
//		 */
//		String loginpass=user.getLoginpass();
//		if(loginpass==null||loginpass.trim().isEmpty()){
//			errors.put("loginpass", "密码不能为空！");
//		}else if(loginname.length()<3||loginname.length()>20){
//			errors.put("loginpass", "密码的长度必须在3-20字符之间！");
//		}
//		
//		/**
//		 * 3.验证码验证:此处需要获取session的真实验证码，因而validateRegist()方法需要获取一个HttpSession对象，以获取vCode
//		 */
//		String verifyCode=user.getVerifyCode();
//		String vCopde=(String) session.getAttribute("vCode");
//		if(verifyCode==null||verifyCode.trim().isEmpty()){
//			errors.put("verifyCode", "验证码不能为空！");
//		}else if(!verifyCode.equalsIgnoreCase(vCopde)){
//			errors.put("verifyCode", "验证码错误！");
//		}
//		
		return errors;
	}
	/**
	 * 用户名是否存在
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public  String ajaxValidateLoginname(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/*1.获取用户名*/
		String loginname=req.getParameter("loginname");
		/*2.通过service得到校验结果*/
		boolean b=userService.ajaxValidateLoginname(loginname);
		/*3.发给客户端*/
		resp.getWriter().print(b);
		return null;
	}
	/**
	 * 邮件是否已经注册
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public  String ajaxValidateEmail(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/*1.获取邮箱*/
		String email=req.getParameter("email");
		/*2.通过service得到校验结果*/
		boolean b=userService.ajaxValidateEmail(email);
		/*3.发给客户端*/
		resp.getWriter().print(b);
		return null;
	}
	/**
	 * 验证码是否正确
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public  String ajaxValidateVerifyCode(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/*1.获取输入框中的验证码*/
		String verifyCode=req.getParameter("verifyCode");
		/*2.获取图片的真正验证码*/
		String vCode=(String)req.getSession().getAttribute("vCode");
		/*3.进行忽略大小写比较，得到结果*/
		boolean b=verifyCode.equalsIgnoreCase(vCode);
		/*4.发送客户端*/
		resp.getWriter().print(b);
		return null;
	}
	/**
	 * 注册功能
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public  String regist(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		/**
		 * 1.封装表单数据到user对象
		 */
		User userForm=CommonUtils.toBean(req.getParameterMap(), User.class);
		/**
		 * 2.校验表单提交的信息（调用自行编写的方法validateRegist(User userForm,HttpSession session)） ,如果校验失败，保存失败信息，返回regist.jsp
		 */
		Map<String, String> errors=new HashMap<String, String>();
		errors=validateRegist(userForm, req.getSession());
		if(errors.size()>0){
			req.setAttribute("errors", errors);
			//若出现错误，需要将之前用户填写的信息进行回填
			req.setAttribute("userForm", userForm);
			return "f:/jsps/user/regist.jsp";
		}
		/**
		 * 3.使用service完成业务
		 */
		userService.regist(userForm);
		/**
		 * 4.保存成功信息，转发页面到msg.jsp
		 */
		req.setAttribute("code","success");
		req.setAttribute("msg", "注册成功，请到邮箱中进行激活");
		/**
		 * return null作用：既不重定向也不进行转发
		 * return "f:/jsps/msg.jsp";  转发到jsps/msg.jsp页面
		 */
		return "f:/jsps/msg.jsp";
	}
	
	/**
	 * 对表单提交的信心进行在一次的验证！其中需要验证验证码的正确定，而验证码的信息保存在了request中的session中，因而该方法需要提供一个HttpSession的参数
	 * 对表单所提交的信息进行逐个校验，如果有错误，使用当前字段为key，错误信息为value，保存到map中
	 * @return
	 */
	Map<String, String> validateRegist(User userForm,HttpSession session){
		Map<String, String> errors=new HashMap<String, String>();
		/**
		 * 1.验证用户名
		 */
		String loginname=userForm.getLoginname();
		if(loginname==null||loginname.trim().isEmpty()){
			errors.put("loginname", "用户名不能为空！");
		}else if(loginname.length()<3||loginname.length()>20){
			errors.put("loginname", "用户名的长度必须在3-20字符之间！");
		}else if(!userService.ajaxValidateLoginname(loginname)) {
			errors.put("loginname", "用户名已注册！");
		}
		/**
		 * 2.验证登录密码
		 */
		String loginpass=userForm.getLoginpass();
		if(loginpass==null||loginpass.trim().isEmpty()){
			errors.put("loginpass", "密码不能为空！");
		}else if(loginname.length()<3||loginname.length()>20){
			errors.put("loginpass", "密码的长度必须在3-20字符之间！");
		}
		/**
		 * 3.确认密码验证
		 */
		String reloginpass=userForm.getReloginpass();
		if(reloginpass==null||reloginpass.trim().isEmpty()){
			errors.put("reloginpass", "确认密码不能为空！");
		}else if(!reloginpass.equals(loginpass)){
			errors.put("reloginpass", "两次密码不一致！");
		}
		/**
		 * 4.Email验证:注意：使用正则表达式时，调用String的match(regx)进行验证。
		 * 其中regx两边的/需要去掉，其只需要在js中使用，告知正则表达式的开始与结束。
		 * 此外，在Java中\需要使用转移字符\进行转译
		 */
		String email=userForm.getEmail();
		if(email==null||email.trim().isEmpty()){
			errors.put("email", "邮箱不能为空！");
		}else if(!email.matches("^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\\.[a-zA-Z0-9_-]{2,3}){1,2})$")){
			errors.put("email", "邮箱格式不正确！");
		}else if(!userService.ajaxValidateEmail(email)) {
			errors.put("email", "该邮箱已注册！");
		}
		/**
		 * 5.验证码验证:此处需要获取session的真实验证码，因而validateRegist()方法需要获取一个HttpSession对象，以获取vCode
		 */
		String verifyCode=userForm.getVerifyCode();
		String vCopde=(String) session.getAttribute("vCode");
		if(verifyCode==null||verifyCode.trim().isEmpty()){
			errors.put("verifyCode", "验证码不能为空！");
		}else if(!verifyCode.equalsIgnoreCase(vCopde)){
			errors.put("verifyCode", "验证码错误！");
		}
		
		return errors;
	}
	
	/**
	 * 激活功能！
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public  String activation(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String code=req.getParameter("activationCode");
		try {
			userService.activation(code);
			req.setAttribute("msg", "激活成功，请进行登录！");
			req.setAttribute("code","success");//通知msg.jsp显示正确图片
		} catch (UserException e) {
			// 说明service抛出了异常信息
			req.setAttribute("msg", e.getMessage());
			req.setAttribute("code","error");//通知msg.jsp显示错误图片
		}
		return "f:/jsps/msg.jsp";
	}
}
